#include "level.h"
#include "../tinyxml/tinyxml.h"


#include <iostream>
#include <fstream>

using namespace std;

void Level::saveLevel(string levelFilePath){
	ofstream ld;
	ld.open(levelFilePath.c_str());
	if(ld){
		ld << "<?xml version=\"1.0\"?>" << endl;
		ld << "<level>" << endl;
		ld << "\t<name> " << name << " </name>" << endl;
		ld << "\t<description> " << description << " </description>" << endl;
		ld << "\t<previewFilePath> " << previewFilePath << " </previewFilePath>" <<endl;
		ld << "\t<goalScore> " << goalScore << " </goalScore>" <<endl;
		ld << "\t<mapDimension>\n" << "\t\t<x> " << map.getMapDimensionX() << " </x>\n" <<
									  "\t\t<y> " << map.getMapDimensionY() << " </y>\n" <<
									  "\t\t<z> " << map.getMapDimensionZ() << " </z>\n";
		ld << "\t</mapDimension>\n";
		ld << "\t<heightMapFile> " << map.getHeightMapFilePath() << " </heightMapFile>" << endl;
		ld << "\t<seaLevel> " << map.getSeaLevel() << " </seaLevel>" <<endl;
		ld << "\t<islands> \n";
		for(unsigned int i=0;i<islands.size();i++)
		{
			ld << "\t\t<island>\n";
			ld << "\t\t\t<islandId> " << islands[i].getIslandId() << " </islandId>" <<endl;
			ld << "\t\t\t<reward> " << islands[i].getReward() << " </reward>" <<endl;
			ld << "\t\t\t<points>\n";
			for(unsigned int j=0;j<islands[i].getPoints().size();j++)
			{
				ld << "\t\t\t\t<point>\n";
				ld << "\t\t\t\t\t<x> " << islands[i].getPoints()[j].first << " </x>" << endl;
				ld << "\t\t\t\t\t<y> " << islands[i].getPoints()[j].second << " </y>" << endl;
				ld << "\t\t\t\t</point>\n";
			}
			ld << "\t\t\t</points>\n";

			ld << "\t\t</island>\n";
		}
		ld << "\t</islands> \n";

		ld << "\t<ports>\n";
		for(unsigned int i=0;i<ports.size();i++)
		{
			ld << "\t\t<port>\n";
			ld << "\t\t\t<player> " << ports[i].getPlayerId() << " </player>\n";
			ld << "\t\t\t<position>\n"<<
					"\t\t\t\t<x> " << ports[i].getPosition().first << " </x>\n" <<
					"\t\t\t\t<y> " << ports[i].getPosition().second << " </y>\n";
			ld << "\t\t\t</position>\n";
			ld << "\t\t\t<orientation> " << ports[i].getOrientation() << " </orientation>"<<endl;
			ld << "\t\t</port>\n";
		}
		ld << "\t</ports>\n";

		ld << "\t<battleShips>\n";
		for(unsigned int i=0;i<ships.size();i++)
		{
			ld << "\t\t<battleShip>\n";
			ld << "\t\t\t<player> " << ships[i].getPlayer() << " </player>" << endl;
			ld << "\t\t\t<initialPosition>\n" << "\t\t\t\t<x> "<< ships[i].getInitialPosition().first << " </x>\n"
												"\t\t\t\t<y> " << ships[i].getInitialPosition().second << " </y>\n";
			ld << "\t\t\t</initialPosition>" <<endl;
			ld << "\t\t\t<initialOrientation> " << ships[i].getInitialOrientation() << " </initialOrientation>\n";

			ld << "\t\t\t<portPosition>\n" << "\t\t\t\t<x> "<< ships[i].getPortPosition().first << " </x>\n"
												"\t\t\t\t<y> " << ships[i].getPortPosition().second << " </y>\n";
			ld << "\t\t\t</portPosition>" <<endl;
			ld << "\t\t\t<portOrientation> " << ships[i].getPortOrientation() << " </portOrientation>\n";

			ld << "\t\t</battleShip>\n";
		}
		ld <<"\t</battleShips>\n";

		ld << "\t<tradeRoutes>\n";
		for(unsigned int i=0;i<routes.size();i++)
		{
			ld << "\t\t<tradeRoute>\n" ;
			ld << "\t\t\t<routeId> " << routes[i].getRouteId() << " </routeId>\n";
			ld << "\t\t\t<from> " << routes[i].getFrom() << " </from>\n";
			ld << "\t\t\t<to> " << routes[i].getTo() << " </to>\n";
			ld << "\t\t\t<path>\n";
			for(unsigned int j=0;j<routes[i].getPoints().size();j++)
			{
				ld << "\t\t\t\t<point>\n";
				ld << "\t\t\t\t\t<x> " << routes[i].getPoints()[j].first << " </x>\n";
				ld << "\t\t\t\t\t<y> " << routes[i].getPoints()[j].second << " </y>\n";
				ld << "\t\t\t\t</point>\n";
			}
			ld << "\t\t\t</path>\n";
			ld << "\t\t</tradeRoute>\n" ;
		}
		ld << "\t</tradeRoutes>\n";

		ld << "\t<bonusPacks>\n";
		for(unsigned int i=0;i<packs.size(); i++)
		{
			ld << "\t\t<bonusPack>\n";
			ld << "\t\t\t<start> " << packs[i].getStartTime() << " </start>" <<endl;
			ld << "\t\t\t<interval> " << packs[i].getInterval() << " </interval>" <<endl;
			ld << "\t\t\t<type> " << packs[i].getType() << " </type>" <<endl;
			ld << "\t\t\t<position>\n";
			ld << "\t\t\t\t<x> " << packs[i].getPosition().first << " </x>\n" <<
					"\t\t\t\t<y> "<< packs[i].getPosition().second << " </y>\n";
			ld << "\t\t\t</position>\n";
			ld << "\t\t</bonusPack>\n";
		}
		ld << "\t</bonusPacks>\n";
		ld << "</level>";

		ld.close();
	}
	else cout << "There was an error while opening the save file.\n " ;
};

void Level::loadLevel(string levelFilePath)
{
	TiXmlDocument doc(levelFilePath.c_str());
	if (doc.LoadFile())
		cout << "Printing started for: "<< levelFilePath << " ..." << endl;
	else{
		cout << "Failed to load file: " << levelFilePath<< endl;
		return;
	}

	TiXmlNode* root;
	TiXmlElement* nextEl;

	root = doc.FirstChildElement();
	//cout << root->Value() <<  " " << root->Type() <<endl;
	if(root!=NULL)
	{
	//	cout << "111" <<endl;
		fflush(stdout);
		nextEl = root->FirstChildElement();
		while(nextEl){
			if(!strcmp(nextEl->Value(),"name")){
				name = nextEl->GetText();
	//			cout << name << endl;
			}
			else if(!strcmp(nextEl->Value(),"description")){
				description = nextEl->GetText();
		//		cout << description << endl;
			}
			else if(!strcmp(nextEl->Value(),"previewFilePath")){
				if(nextEl->GetText())
					previewFilePath = nextEl->GetText();
		//		cout << previewFilePath << endl;
			}
			else if(!strcmp(nextEl->Value(),"goalScore")){
				goalScore = atoi(nextEl->GetText());
		//		cout << goalScore << endl;
			}
			else if(!strcmp(nextEl->Value(),"mapDimension")){
				TiXmlElement* sibEl;
				sibEl = nextEl->FirstChildElement();
				float x = atof(sibEl->GetText());
				sibEl = sibEl->NextSiblingElement();
				float y = atof(sibEl->GetText());
				sibEl = sibEl->NextSiblingElement();
				float z = atof(sibEl->GetText());
				map.setMapDimensionX(x);
				map.setMapDimensionY(y);
				map.setMapDimensionZ(z);
		//		cout << "map x: " << map.getMapDimensionX() << " y: " << map.getMapDimensionY() << " z: " << map.getMapDimensionZ() << endl;
			}
			else if(!strcmp(nextEl->Value(),"heightMapFile")){
				map.setHeightMapFilePath(nextEl->GetText());
		//		cout << map.getHeightMapFilePath();
			}
			else if(!strcmp(nextEl->Value(),"seaLevel")){
				map.setSeaLevel(atof(nextEl->GetText()));
		//		cout << atof(nextEl->GetText()) << endl;
			}
			else if(!strcmp(nextEl->Value() , "islands"))
			{
				TiXmlElement* oneisland;
				TiXmlElement* onesib;
				TiXmlElement* onepoint;
				vector<pair<float,float> > islandPoints;
				vector<Island> newislands;

				for(oneisland= nextEl->FirstChildElement();oneisland!=0;oneisland=oneisland->NextSiblingElement()){

					islandPoints.clear();
					onesib = oneisland->FirstChildElement();
					Island newIsland;
					newIsland.setIslandId(atoi(onesib->GetText()));//island idsini okur
					onesib = onesib->NextSiblingElement();
					newIsland.setReward(atoi(onesib->GetText()));//island rewardini okur
					onesib = onesib->NextSiblingElement();
					onepoint = onesib->FirstChildElement();//ilk island pointini alir
					islandPoints.push_back(make_pair(atof(onepoint->FirstChildElement()->GetText()),
							atof(onepoint->FirstChildElement()->NextSiblingElement()->GetText())));
					//diger pointleri almaya baslar
					while(onepoint->NextSiblingElement()){
						onepoint = onepoint->NextSiblingElement();
						islandPoints.push_back(make_pair(atof(onepoint->FirstChildElement()->GetText()),
							atof(onepoint->FirstChildElement()->NextSiblingElement()->GetText())));
			//		cout << "point " << atof(onepoint->FirstChildElement()->GetText()) <<endl;
					}
					newIsland.setPoints(islandPoints);
					newislands.push_back(newIsland);

			//		cout<< "id: " << newIsland.getIslandId() <<endl;
			//		cout<< "reward: " << newIsland.getReward() <<endl;
				}
				islands = newislands;

			}
			else if(!strcmp(nextEl->Value() , "ports")){
				TiXmlElement* onePort;
				TiXmlElement* oneSib;
				vector<Port> newports;
				Port newPort;
				for(onePort=nextEl->FirstChildElement();onePort!=0;onePort=onePort->NextSiblingElement()){

					oneSib=onePort->FirstChildElement();//player id elementi
					newPort.setPlayerId(atoi(oneSib->GetText()));
					oneSib=oneSib->NextSiblingElement();//point elementi
					newPort.setPosition(make_pair(atof(oneSib->FirstChildElement()->GetText()),
							atof(oneSib->FirstChildElement()->NextSiblingElement()->GetText())));
					oneSib=oneSib->NextSiblingElement();//orientation
					newPort.setOrientation(atof(oneSib->GetText()));
			//		cout << "port playerid: " << newPort.getPlayerId() << " point x: " << newPort.getPosition().first <<
			//		" y: " << newPort.getPosition().second << " orient: " << newPort.getOrientation() <<  endl;
					newports.push_back(newPort);
				}
				ports = newports;
			}
			else if(!strcmp(nextEl->Value() , "battleShips")){
				TiXmlElement* oneShip;
				TiXmlElement* oneSib;
				vector<BattleShip> newShips;
				BattleShip newShip;
				for(oneShip=nextEl->FirstChildElement();oneShip!=0;oneShip=oneShip->NextSiblingElement()){
					oneSib = oneShip->FirstChildElement(); //player idsi
					newShip.setPlayer(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement();
					newShip.setInitialPosition(make_pair(atof(oneSib->FirstChildElement()->GetText()),
							atof(oneSib->FirstChildElement()->NextSiblingElement()->GetText())));
					oneSib = oneSib->NextSiblingElement();
					newShip.setInitialOrientation(atof(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement();
					newShip.setPortPosition(make_pair(atof(oneSib->FirstChildElement()->GetText()),
							atof(oneSib->FirstChildElement()->NextSiblingElement()->GetText())));
					oneSib = oneSib->NextSiblingElement();
					newShip.setPortOrientation(atof(oneSib->GetText()));
					newShips.push_back(newShip);
			//		cout << "battle initial or: "<< newShip.getInitialOrientation() << " initial pos: " <<
			//			newShip.getInitialPosition().first << ", " << newShip.getInitialPosition().second <<
			//			"port or: " << newShip.getPortOrientation() << " pos: " << newShip.getPortPosition().first <<
			//			" " << newShip.getPortPosition().second << endl;
				}
				ships = newShips;
			}
			else if(!strcmp(nextEl->Value() , "tradeRoutes")){
				TiXmlElement* oneRoute;
				TiXmlElement* oneSib;
				vector<TradeRoute> newRoutes;
				//vector<pair<float,float> > paths;
				for(oneRoute=nextEl->FirstChildElement();oneRoute!=0;oneRoute=oneRoute->NextSiblingElement()){
					TradeRoute newRoute;
					newRoute.getPoints().clear();
					oneSib = oneRoute->FirstChildElement(); //route idsi
					newRoute.setRouteId(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement(); //from
					newRoute.setFrom(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement(); //path
					newRoute.setTo(atoi(oneSib->GetText()));
					for(oneSib=oneSib->NextSiblingElement()->FirstChildElement();oneSib!=0;oneSib=oneSib->NextSiblingElement()){
						newRoute.pushPoint(make_pair(atof(oneSib->FirstChildElement()->GetText()),
								atof(oneSib->FirstChildElement()->NextSiblingElement()->GetText())));

					}
					newRoutes.push_back(newRoute);
				}
				routes = newRoutes;
			}
			else if(!strcmp(nextEl->Value() , "bonusPacks")){
				TiXmlElement* onePack;
				TiXmlElement* oneSib;
				vector<BonusPack> newPacks;
				BonusPack newPack;
				for(onePack=nextEl->FirstChildElement();onePack!=0;onePack=onePack->NextSiblingElement()){
					oneSib = onePack->FirstChildElement();///time element
					newPack.setStartTime(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement();//time interval
					newPack.setInterval(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement();//type
					newPack.setType(atoi(oneSib->GetText()));
					oneSib = oneSib->NextSiblingElement();//position
					newPack.setPosition(make_pair(atof(oneSib->FirstChildElement()->GetText()),
							atof(oneSib->FirstChildElement()->NextSiblingElement()->GetText())));
					newPacks.push_back(newPack);
				}
				packs = newPacks;
			}

			nextEl=nextEl->NextSiblingElement();
		}

	}
};
